<?php

namespace app\admin\service\admin;

use app\admin\model\admin\Dict as DictModel;
use app\admin\model\admin\I18n as I18nModel;
use app\admin\service\common\SqlProcessService;
use app\common\Constants;
use app\common\exception\BusinessException;
use app\common\facade\Principal;
use think\db\Query;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Lang;
use think\facade\Log;

class DictService
{
    /**
     * 下面的函数仅处理了系统字典中的一些业务
     * 没有考虑数据权限问题
     * 如需实现数据权限，请自行处理
     */

    protected $sqlProcessService;

    public function __construct()
    {
        $this->sqlProcessService = new SqlProcessService();
    }

    /*
     * 查询菜单作为树形组件的选项
     * 仅设计开发和管理员使用，无权限限制
     * sys_menu_tree_options
     */
    public function sysAdminMenuTreeOptions(): array
    {
        try {
            $langSet = Lang::getLangSet();
            $list = Db::name('dev_menu')->alias('a')
                ->leftJoin('admin_i18n b', 'a.key = b.key and b.lang_code=' . "'" . $langSet . "'")
                ->field('a.id as value,IFNULL(b.`value`,a.`name`) as label,a.pid')
                ->where('a.status', 1)
                ->where('a.app', 'admin')
                ->whereNull('a.delete_time')
                ->order('a.sort desc')
                ->select()->toArray();
            if ($list) {
                $tools = new \Raiseinfo\Tools();
                $tempArray = $tools->buildTree($list, true, 0, 'value');

                return [['value' => 0, 'label' => lang(Constants::COMMON_ROOT), 'children' => $tempArray]];
            } else {
                return [['value' => 0, 'label' => lang(Constants::COMMON_ROOT), 'children' => []]];
            }
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    /*
 * 查询接口作为树形组件的选项
 * 仅设计开发和管理员使用，无权限限制
 * sys_api_tree_options
 */
    public function sysAdminApiTreeOptions(): array
    {
        try {
            $langSet = Lang::getLangSet();
            $list = Db::name('dev_menu')->alias('a')
                ->leftJoin('admin_i18n b', 'a.key = b.key and b.lang_code=' . "'" . $langSet . "'")
                ->field('a.id as value,IFNULL(b.`value`,a.`name`) as label,a.pid')
                ->where('a.status', 1)
                ->where('a.app', 'api')
                ->whereNull('a.delete_time')
                ->order('a.sort desc')
                ->select()->toArray();
            if ($list) {
                $tools = new \Raiseinfo\Tools();
                $tempArray = $tools->buildTree($list, true, 0, 'value');

                return [['value' => 0, 'label' => lang(Constants::COMMON_ROOT), 'children' => $tempArray]];
            } else {
                return [['value' => 0, 'label' => lang(Constants::COMMON_ROOT), 'children' => []]];
            }
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }


    /*
     * 查询菜单作为下拉框的下拉选项
     * 仅设计开发和管理员使用，无权限限制
     * sys_menu_options
     */
    public function sysAdminMenuOptions(): array
    {
        try {
            $langSet = Lang::getLangSet();
            $list = Db::name('dev_menu')->alias('a')
                ->leftJoin('admin_i18n b', 'a.key = b.key and b.lang_code=' . "'" . $langSet . "'")
                ->field('a.id as value,IFNULL(b.`value`,a.`name`) as label')
                ->where('a.status', 1)
                ->where('a.app', 'admin')
                ->whereNull('a.delete_time')
                ->order('a.sort desc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    /**
     * 后台数据库字段类型下拉选项
     * sys_field_options
     * @return array
     */
    public function sysFieldOptions(): array
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'data_type')
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    /**
     * 后台表单类型下拉选项
     * sys_admin_form_options
     * @return array
     */
    public function sysAdminFormOptions(): array
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'field')
                ->where('for_admin', '1')
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    /**
     * 接口表单类型下拉选项
     * sys_api_form_options
     * @return array
     */
    public function sysApiFormOptions(): array
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'field')
                ->where('for_api', '1')
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    public function sysFormActionOptions()
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'action')
                ->where('for_admin', '1')
                ->where('for_template', 'form')
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }


    /**
     * 后台方法类型下拉选项
     * sys_admin_action_options
     * @return array
     */
    public function sysAdminActionOptions(): array
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'action')
                ->where('for_admin', '1')
                ->whereIn('for_template', ['table','any'])
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    /**
     * 后台表单类型下拉选项(菜单未设置数据库表的时候)
     * sys_admin_form_options
     * @return array
     */
    public function sysAdminActionExceptTableOptions(): array
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'action')
                ->where('for_template', 'any')
                ->where('for_admin', '1')
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    /**
     * 接口方法类型下拉选项
     * sys_api_action_options
     * @return array
     */
    public function sysApiActionOptions(): array
    {
        try {
            $list = Db::name('dev_prop')->field('value,label')
                ->where('status', 1)
                ->where('type', 'action')
                ->where('for_api', '1')
                ->whereIn('for_template', ['table','any'])
                ->order('sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }


    /**
     * 查询菜单对应的数据库表名（无前缀）
     * sys_menu_table
     * @return array
     */
    public function sysMenuTable(): array
    {
        try {
            $langSet = Lang::getLangSet();
            $list = Db::name('dev_menu')->alias('a')
                ->leftJoin('admin_i18n b', 'a.key = b.key and b.lang_code=' . "'" . $langSet . "'")
                ->field("b.value as label,a.table_name as value")
                ->where('a.status', 1)
                ->whereNotNull('a.table_name')
                ->order('a.sort asc')
                ->select()->toArray();
            return $list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }

    public function sysAdminLangOptions(): array
    {
        $lang_map = config('rds.language');
        try {
            $langs = I18nModel::field('lang_code')->distinct(true)->select();
            $lang_list = [];
            if ($langs) {
                foreach ($langs as $index => $lang) {
                    $lang_code = $lang['lang_code'];
                    if (isset($lang_map[$lang_code])) {
                        $lang_name = $lang_map[$lang_code];
                    } else {
                        $lang_name = $lang_code;
                    }
                    $lang_list[$index]['label'] = $lang_name;
                    $lang_list[$index]['value'] = $lang_code;
                }
            }
            return $lang_list;
        } catch (\Exception $e) {
            throw new ValidateException($e->getMessage());
        }
    }


    /**
     * 根据名称查询字典
     */
    public function getDictData($params): array
    {
        try {
            if (!$params['code']) {
                throw new BusinessException(Constants::E_COMMON_INVALID_PARAM);
            }
            $dictInfo = DictModel::where(['code' => $params['code'], 'status' => 1])->findOrEmpty();
            if ($dictInfo->isEmpty()) {
                throw new BusinessException(Constants::E_COMMON_RECORD_NOT_FOUND);
            }
            $data = [];
            if ($dictInfo['sql']) {
                if ($dictInfo['type'] == 1) {
                    $data = $dictInfo['sql'];
                }
                if ($dictInfo['type'] === 2) { // 根据 SQL 查询语句获得数据
                    trace('SQL');
                    // 这里数据库连接默认是 mysql
                    $data = $this->sqlProcessService->parseSqlToDict($dictInfo['sql'], $params['perms']);
                }
                if ($dictInfo['type'] === 3) { // 根据Service类的方法名调用方法获得数据
                    $methodName = $dictInfo['sql'];
                    $dictService = app()->make(DictService::class);
                    $data = $dictService->{$methodName}();
                }
            } else {
                throw new BusinessException(Constants::E_COMMON_RECORD_NOT_FOUND);
            }
            return $data;
        } catch (\Exception $e) {
            trace([
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'params' => $params,
                'error_message' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ], 'debug');
            throw $e;
        }
    }

}